const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
const dynamicArgAttribute = /^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+?\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`
const qnameCapture = `((?:${ncname}\\:)?${ncname})`
const startTagOpen = new RegExp(`^<${qnameCapture}`)
const startTagClose = /^\s*(\/?)>/
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)
const doctype = /^<!DOCTYPE [^>]+>/i

let root = null // ast语法树的树根
let currentParent = null // 标识当前父亲是谁
let stack = []
const ELEMENT_TYPE = 1
const TEXT_TYPE = 3
function createASTElement(tagName,attrs){
    return {
        tag: tagName,
        type: ELEMENT_TYPE,
        children: [],
        attrs,
        parent: null
    }
}
  
function start(tagName,attrs){
    let element = createASTElement(tagName,attrs)
    stack.push(element)
    // 遇到开始标签，就创建一个ast元素
    if(!root){
        root = element
    }
    currentParent = element
}
function chars(text){
    text = text.replace(/\s/g,'')
    if(text){
        currentParent.children.push({
            text,
            type:TEXT_TYPE
        })
    }
}

function end(tagName){
    let element = stack.pop()
    currentParent = stack[stack.length - 1]
    if(currentParent){
        element.parent = currentParent
        currentParent.children.push(element)
    }

}

export function parseHTML(html){
    while(html){
        let textEnd = html.indexOf('<')
        if(textEnd == 0){
            // 如果当前索引为0，肯定是一个标签，
            let startTagMatch = parseStartTag(); // 通过这个方法获取开始标签
             if(startTagMatch){
                 start(startTagMatch.tagName,startTagMatch.attrs)
                continue;
             }

             let endTagMatch = html.match(endTag)
             if(endTagMatch){
                 advance(endTagMatch[0].length)
                 end(endTagMatch[1])
                 continue
             }
        }
        let text;
        // 说明是文本
        if(textEnd >= 0){
            text = html.substring(0,textEnd)
        }
        if(text){
            advance(text.length)
            chars(text)
            continue
        }
    }

    function parseStartTag(){
        let start = html.match(startTagOpen)
        if(start && start.length){
            const match = {
                tagName:start[1],
                attrs: []
            }
            advance(start[0].length)
            let end,attr
        while (!(end = html.match(startTagClose)) && (attr = html.match(attribute))) {
            advance(attr[0].length)
            match.attrs.push({
                name: attr[1],
                value: attr[3]|| attr[4]|| attr[5]
            })
        }
        if(end){
            advance(end[0].length)
        }   
        return match  
        }
        
    }
    function advance(step){
        html = html.substring(step)
    }

    return root

}